﻿using RunUI.Attributes;
using RunUI.SysModels;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RunUI.AspNetCore
{
    internal class DefaultForeignRelationProvider : IForeignRelationProvider
    {
        readonly IFreeSql orm;
        readonly ITenantProvider tenantProvider;
        public DefaultForeignRelationProvider(IFreeSql freeSql, ITenantProvider tenantProvider)
        {
            orm = freeSql;
            this.tenantProvider = tenantProvider;

        }

        class StringEqualityComparer : IEqualityComparer<string>
        {
            public bool Equals(string x, string y)
            {
                if (x == y) return true;
                if (x == null && y != null) return false;
                if (x != null && y == null) return false;
                return x.EqualsIgnoreCase(y);
            }

            public int GetHashCode([DisallowNull] string obj)
            {
                return obj.GetHashCode();
            }
        }
        public async Task<List<LabelValue>> GetForeignRelationsAsync(ForeignRelationAttribute foreign, string[] values)
        {
            Type type = foreign.Table;
            string valueColumn = foreign.ValueColumn;
            string[] showColumns = foreign.ShowColumns;

            if (values == null) throw new ArgumentNullException(nameof(type));
            values = values.Where(i => i.HasValue()).Distinct(new StringEqualityComparer()).ToArray();
            
            if (!values.Any())
            {
                return new List<LabelValue>();
            }
            if (foreign.Expression.HasValue())
            {
                return await GetForeignRelationsWithExpressionAsync(foreign.Expression, values);
            }


            if (type == null) throw new ArgumentNullException(nameof(type), "传入的外键表类型错误");
            if (valueColumn.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(type));
            if (showColumns == null || showColumns.Any(i => i.IsNullOrWhiteSpace()))
            {
                showColumns = new[] { valueColumn };
            }

            string tenantId = null;


            if (tenantProvider != null)
            {
                tenantId = await tenantProvider.GetTenantId();
            }

            var allColumns = new List<string>() { valueColumn };
            allColumns.AddRange(showColumns);
            allColumns = allColumns.Distinct(new StringEqualityComparer()).ToList();

            var sql = $"select * from {type.Name} b where b.{valueColumn} in ('{values.Join("', '")}')";

            DataTable dt1 = orm.Select<object>().WithSql(sql).ToDataTable(allColumns.Join(","));
            var list = new List<LabelValue>();
            foreach (DataRow row in dt1.Rows)
            {
                var item = new LabelValue
                {
                    Value = row[valueColumn].ToStringExt(),
                    Label = showColumns.Select(i => row[i].ToStringExt()).Join(foreign.Separator.NullWhiteSpaceForDefault("-"))
                };
                list.Add(item);
            }
            return list;
        }

        public async Task<List<LabelValue>> GetForeignRelationsWithExpressionAsync(string expressType, string[] values)
        {
            if (expressType == null)
            {
                await Task.CompletedTask;
                return new List<LabelValue>();
            }

            if (expressType.EqualsIgnoreCase("GetTenantName"))
            {
                var list = await orm.Select<TTenant>().Where(i => values.Contains(i.Id)).ToListAsync(i => new LabelValue { Value = i.Id, Label = i.Name });
                return list;
            }
            await Task.CompletedTask;
            return new List<LabelValue>();
        }
    }
}
